home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1992 June: ROMin Holiday / ADC Developer CD (1992-06) (''ROMin Holiday'')_iso / Developer Connection - 06-1992.iso / Development Platforms / Apple II / Essentials / Technical.Notes / IIGS / TN.IIGS.080 < prev    next >
Encoding:
Text File  |  1990-04-03  |  29.4 KB  |  538 lines  |  [TEXT/pdos]

  1. Apple II
  2. Technical Notes
  3. _____________________________________________________________________________
  4.                                                   Developer Technical Support
  5.  
  6. Apple IIGS
  7. #80:    QuickDraw II Clipping
  8.  
  9. Written by:    Eric Soldan    March 1990
  10.  
  11. This Technical Note explains a lot about QuickDraw II operation, specifically 
  12. clipping.
  13. _____________________________________________________________________________
  14.  
  15. Before Beginning
  16.  
  17. Before beginning this Note, some statements, disclaimers, and definitions:
  18.  
  19.   1.  This is not a substitute for the QuickDraw II introduction in the 
  20.       Apple IIGS Toolbox Reference, but rather a supplement.
  21.   2.  A pixelmap is a series of bytes that hold pixel data whose 
  22.       rectangular shape is defined by a LocInfo structure.
  23.  
  24. This Note describes in great detail the way that QuickDraw II does things with 
  25. pixelmaps.  It begins with a description of the LocInfo structure, which is 
  26. the most important thing to understand in terms of QuickDraw II pixelmap 
  27. management.  Once this is understood, this Note covers how it applies to using 
  28. functions such as PPToPort, PaintPixels, and CopyPixels.  And once this is 
  29. understood, it then describes how LocInfo structures are used to control 
  30. drawing into a grafPort.  (PPToPort is used in this Note.  PaintPixels and 
  31. CopyPixels are very close in function to PaintPixels.  The information and 
  32. theory in this Note also apply to these calls.)
  33.  
  34. Understanding the material in this Note should help you better understand the 
  35. entire toolbox.  It is surprising how much can be accomplished with the 
  36. toolbox without completely understanding these concepts; it is also surprising 
  37. how much easier programming with the toolbox gets when these concepts are 
  38. fully understood.
  39.  
  40. Note:  Structures are written with C syntax in this Note.  In addition, 
  41.        this Note uses the screen address 0xE12000L.  The possibility of 
  42.        shadowing being active and the screen address being 0x12000L is 
  43.        ignored.
  44.  
  45.  
  46. The Beginning
  47.  
  48. One must begin with the LocInfo structure, which is as follows:
  49.  
  50. struct LocInfo {
  51.        Word          portSCB;              /* SCB in low byte */
  52.        Pointer       ptrToPixImage;        /* ImageRef */
  53.        Word          width;                /* Width */
  54.        Rect          boundsRect;           /* BoundsRect */
  55. };
  56.  
  57. For this Note, one can change this structure a little bit by calling the width 
  58. element rowBytes.  This convention is good because rowBytes is more 
  59. descriptive than width (it indicates that one is measuring the width in bytes) 
  60. and it allows one to use the word "width" elsewhere in this Note without 
  61. confusion.  So for the purposes of the Note, the new LocInfo structure 
  62. definition is as follows:
  63.  
  64. struct LocInfo {
  65.        Word          portSCB;              /* SCB in low byte */
  66.        Pointer       ptrToPixImage;        /* ImageRef */
  67.        Word          rowBytes;             /* Width in bytes*/
  68.        Rect          boundsRect;           /* BoundsRect */
  69. };
  70.  
  71. The ptrToPixImage field is a pointer to some block of bytes in memory.  (This 
  72. block of bytes is referred to as the pixImage from here on.)  A pixImage 
  73. doesn't have any inherent shape.  QuickDraw II deals with it as a rectangle, 
  74. and the LocInfo record defines the rectangularity of it.
  75.  
  76. When saving a 32,000 byte screen image, one doesn't save the number of bytes 
  77. of which each row consists.  One assumes that each row is 160 bytes by 
  78. convention, and this is a safe assumption, since the IIGS video hardware 
  79. expects 160 bytes.  But the point is that in the 32,000 bytes of screen data, 
  80. there is no indicator as to the specific size of a row.  One must  just know 
  81. that it is 160 bytes per row.  This size is fine for screen shots, but it is 
  82. not fine when different pixelmaps can be different widths.  If they can be 
  83. different widths, then one also needs some information as to what those widths 
  84. are, hence the portSCB, rowBytes, and boundsRect fields in a LocInfo 
  85. structure.
  86.  
  87. The boundsRect and portSCB fields tell the shape of the pixelmap in pixels, 
  88. the boundsRect tells how many pixels wide and tall the pixelmap is, and the 
  89. portSCB tells how big those pixels are (320-mode pixels are four bits wide and 
  90. 640-mode pixels are two bits wide).  One would think that this would be enough 
  91. information to determine the size of the pixImage, but it isn't.  The rowBytes 
  92. can be larger than the boundsRect/portSCB would indicate (see Figure 1).  This 
  93. situation is legal; it means that some bytes are being wasted, but it is 
  94. legal.
  95.  
  96.  ___________________________ rowBytes ______________________
  97. |                                                           |
  98. |      boundsRect                                           |
  99.  ___________________________________________ ................
  100. |0,0 .......................................|................
  101. |...........................................|................
  102. |...........................................|................
  103. |...........................................|................
  104. |...........................................|................
  105. |...........................................|................
  106. |...........................................|................
  107. |...........................................|................
  108. |...........................................|................
  109. |...........................................|................
  110. |...........................................|................
  111. |...........................................|................
  112. |___________________________________________|................
  113. .............................................313,97..........
  114. .......................................................^.....
  115. .......................................................|.....
  116.                                                        |
  117. _____________________________________________          |
  118.  Block of bytes pointed to by ptrToPixImage. \_________|
  119. _____________________________________________/
  120.  
  121.                       Figure 1-Sample LocInfo Structure
  122.  
  123. One simply has to know the size of the pixImage, since it cannot be determined 
  124. by the LocInfo information.  If the pixImage is the screen, then it is 32,000 
  125. bytes.  If it is a fixed or locked handle, then one can do a FindHandle on the 
  126. pointer followed by a GetHandleSize on the found handle.
  127.  
  128. Figure 1 represents a sample LocInfo structure.  The portSCB (although not 
  129. pictured) is also relevant, as it determines the size of the pixels.  If the 
  130. pixelmap is a 320-mode pixelmap, one could change it to a 640-mode pixelmap by 
  131. changing the portSCB to 640 mode and doubling the width of the boundsRect.  In 
  132. doing this conversion, note that rowBytes is not affected and that the 
  133. pixImage does not change size.
  134.  
  135. In the example illustrated in Figure 1, the pixImage is bigger than the 
  136. boundsRect, but again, this is okay.  However, this is not the case for the 
  137. screen, where the rowBytes is 160 and the height of the boundsRect is 200 (the 
  138. size of the screen is exactly equal to 160 * 200 = 32,000).
  139.  
  140. There are some rules to determining the rowBytes value.  First, rowBytes must 
  141. not be too small.  This is obvious.  Second, rowBytes must be evenly divisible 
  142. by eight.  This is not at all obvious, but it is very important.  QuickDraw II 
  143. makes some assumptions for speed, and one of them is that rowBytes is a 
  144. multiple of eight.
  145.  
  146. So much for describing the LocInfo structure.  Now for how to use it via 
  147. PPToPort.
  148.  
  149. PPToPort accepts (among other things) a pointer to a source LocInfo record and 
  150. a pointer to a source rectangle.  PPToPort does not use the source rectangle 
  151. directly; it first intersects it with the boundsRect in the LocInfo record, 
  152. and it uses this intersection rectangle instead.  This intersection rectangle 
  153. guarantees that the area involved is completely enclosed by the boundsRect 
  154. (and therefore within the pixImage).  If the source rectangle is entirely 
  155. outside the boundsRect, then the intersection of the source rectangle and the 
  156. boundsRect is empty, thus nothing is drawn.
  157.  
  158.  ___________________________ rowBytes ______________________
  159. |                                                           |
  160. |      boundsRect                                           |
  161.  ___________________________________________ ................
  162. |0,0........................................|................
  163. |.............intersection rectangle........|.........sourceRect
  164. |.......____________________________________|_____________________________
  165. |......|50,25 / / / / / / / / / / / / / / / |................             |
  166. |......| / / / / / / / / / / / / / / / / / /|................             |
  167. |......|/ / / / / / / / / / / / / / / / / / |................             |
  168. |......| / / / / / / / / / / / / / / / / / /|................             |
  169. |......|/ / / / / / / / / / / / / / / / / / |................             |
  170. |......| / / / / / / / / / / / / / /  313,77|................             |
  171. |......|____________________________________|_____________________________|
  172. |...........................................|................          523,77
  173. |...........................................|................
  174. |___________________________________________|................
  175. .........................................313,97..............
  176. .......................................................^.....
  177. .......................................................|.....
  178.                                                        |
  179. _____________________________________________          |
  180.  Block of bytes pointed to by ptrToPixImage. \_________|
  181. _____________________________________________/
  182.  
  183.            Figure 2-Sample LocInfo Structure With sourceRect
  184.  
  185. Figure 2 contains a sourceRect which is not completely contained by the 
  186. boundsRect; the sourceRect is so wide that it even goes beyond the edge of the 
  187. pixImage.  If the entire contents of this rectangle were drawn, the result 
  188. would be quite a mess, since it extends beyond the boundary of the pixelmap.  
  189. However, PPToPort first intersects the sourceRect and the boundsRect, and then 
  190. uses the resulting intersection rectangle (illustrated with a thicker border 
  191. in the figure).  PPToPort uses only the contents of the intersection 
  192. rectangle.
  193.  
  194. Up until now, the boundsRect upper-left corner has always been 0,0.  This is 
  195. an easy way to think of it, but it is not necessary.  The important thing to 
  196. remember about these rectangles is their relation to one another.  If one were 
  197. to offset both the boundsRect and sourceRect in this example, the values for 
  198. the corners of the rectangles would change, but the relationship between the 
  199. two rectangles would stay the same.  Figure 3 illustrates the same example if 
  200. one were to offset both rectangles by -60,-45.
  201.  
  202.  ___________________________ rowBytes ______________________
  203. |                                                           |
  204. |      boundsRect                                           |
  205.  ___________________________________________ ................
  206. |-60,-45....................................|................
  207. |.............intersection rectangle........|.........sourceRect
  208. |.......____________________________________|_____________________________
  209. |......|-10,-20 / / / / / / / / / / / / / / |................             |
  210. |......| / / / / / / / / / / / / / / / / / /|................             |
  211. |......|/ / / / / / / / / / / / / / / / / / |................             |
  212. |......| / / / / / / / / / / / / / / / / / /|................             |
  213. |......|/ / / / / / / / / / / / / / / / / / |................             |
  214. |......| / / / / / / / / / / / / / /  253,32|................             |
  215. |......|____________________________________|_____________________________|
  216. |...........................................|................          463,32
  217. |...........................................|................
  218. |___________________________________________|................
  219. .........................................253,52..............
  220. .......................................................^.....
  221. .......................................................|.....
  222.                                                        |
  223. _____________________________________________          |
  224.  Block of bytes pointed to by ptrToPixImage. \_________|
  225. _____________________________________________/
  226.  
  227.              Figure 3-Sample LocInfo Structure Offset by -60,-45
  228.  
  229. Notice that the same area of the pixImage is involved, even though the 
  230. boundsRect and sourceRect are offset.  When one offsets both the boundsRect 
  231. and sourceRect by the same amount, the referenced part of the pixImage does 
  232. not change--this is an important concept.
  233.  
  234. Time to ask a question that is answered shortly:  "Why isn't the upper-left 
  235. corner of the boundsRect always 0,0?"  Because the LocInfo record isn't always 
  236. a source LocInfo record.  It can also be a destination LocInfo record, and the 
  237. most common pixelmap to which a destination LocInfo record refers is the 
  238. screen.
  239.  
  240. If you had not noticed, the discussion changes gears here--to discuss LocInfo 
  241. records that indicate a destination pixelmap.  Basically, everything is the 
  242. same as has been described with two exceptions.  First, destination pixelmaps 
  243. do not have a sourceRect.  Instead there is a rectangle that describes some 
  244. portion of the destination pixelmap, and this rectangle is called the 
  245. portRect.  Second, the LocInfo record is part of a grafPort, and each grafPort 
  246. has a LocInfo record as part of the grafPort data structure.
  247.  
  248. It is important to remember that a LocInfo record can be used as either a 
  249. source or destination LocInfo.  All a LocInfo record does is define some bytes 
  250. in memory as a pixImage.  Even the screen, which is usually used as a 
  251. destination pixelmap, can be used as a source pixelmap.  There could be 
  252. situations where one might want to take part of the screen and copy it into 
  253. some off-screen pixelmap, and in this case, the screen would be a source of 
  254. pixel data, not a destination.
  255.  
  256. In the case of the screen pixelmap, there are no wasted bytes in the pixImage, 
  257. as all of the screen bytes are enclosed by the boundsRect.  The screen width 
  258. of 160 is evenly divisible by eight, so there is no slop at the right edge, 
  259. and there are no extra rows hanging off the bottom of the boundsRect.
  260.  
  261. Figure 4 shows a sample LocInfo and portRect (every grafPort has a LocInfo and 
  262. a portRect).
  263.  
  264.  __________________ rowBytes _______________
  265. |                                           |
  266. |      boundsRect                           |
  267.  ___________________________________________ 
  268. |0,0........................................|
  269. |.............intersection rectangle........|         portRect
  270. |.......____________________________________|_____________________________
  271. |......|98,54 / / / / / / / / / / / / / / / |                             |
  272. |......| / / / / / / / / / / / / / / / / / /|                             |
  273. |......|/ / / / / / / / / / / / / / / / / / |                             |
  274. |......| / / / / / / / / / / / / / / / / / /|                             |
  275. |......|/ / / / / / / / / / / / / / / / / / |                             |
  276. |......| / / / / / / / / / / / / / / 640,143|                             |
  277. |......|____________________________________|_____________________________|
  278. |...........................................|                          917,143
  279. |........................................<__|______
  280. |___________________________________________|      |
  281.                                          640,200   |
  282.                                                    |
  283. _____________________________________________      |
  284.  Block of bytes pointed to by ptrToPixImage. \_____|
  285.  In the case of the screen, this is $E12000. /
  286. ____________________________________________/
  287.  
  288.                  Figure 4-Sample LocInfo and portRect
  289.  
  290. Following are two important points to remember:
  291.  
  292.   1.  Every grafPort works in local (not global) coordinates (local 
  293.       coordinates are defined soon).
  294.   2.  The origin of the grafPort is the upper-left corner of the 
  295.       portRect.  There is no GetOrigin call; there is a SetOrigin call, 
  296.       but no GetOrigin.  To get the origin of a grafPort, one needs to 
  297.       do a GetPortRect call, and then look at the upper-left corner to 
  298.       determine the current origin of the grafPort.  This is the way to 
  299.       get the origin.
  300.  
  301. In the case of Figure 4, local and global coordinate systems are the same, as 
  302. is always the case when the boundsRect has an upper-left corner of 0,0 (which 
  303. it seldom does).  So, for this exceptional case, one doesn't need a definition 
  304. of local coordinates.  In the global coordinate system, the upper-left corner 
  305. of the screen is 0,0.  In local coordinates, the upper-left corner of the 
  306. screen is whatever the boundsRect says it is.  So when the upper-left corner 
  307. of the boundsRect is 0,0, the global and local coordinate systems are the 
  308. same.
  309.  
  310. In Figure 4, if one tried to draw something to point 0,0, it would not draw--it 
  311. would be clipped because it is outside the portRect.  So even if one tried to 
  312. draw there, it would not change point 0,0.  If a user moved a mouse to that 
  313. location and an application performed a GetMouse (which returns the mouse 
  314. location in the local coordinates of the current grafPort), it would return 
  315. 0,0 as the mouse location.
  316.  
  317. If one did a SetOrigin(0,0), then the boundsRect and portRect would be offset 
  318. by the difference between the old and new origins.  Both rectangles would be 
  319. offset, so the relationship between them would remain the same, as Figure 5 
  320. illustrates.
  321.  
  322.  __________________ rowBytes _______________
  323. |                                           |
  324. |      boundsRect                           |
  325.  ___________________________________________ 
  326. |-98,-54....................................|
  327. |.............intersection rectangle........|         portRect
  328. |.......____________________________________|_____________________________
  329. |......|0,0 / / / / / / / / / / / / / / / / |                             |
  330. |......| / / / / / / / / / / / / / / / / / /|                             |
  331. |......|/ / / / / / / / / / / / / / / / / / |                             |
  332. |......| / / / / / / / / / / / / / / / / / /|                             |
  333. |......|/ / / / / / / / / / / / / / / / / / |                             |
  334. |......| / / / / / / / / / / / / / /  542,89|                             |
  335. |......|____________________________________|_____________________________|
  336. |...........................................|                          819,89
  337. |........................................<__|______
  338. |___________________________________________|      |
  339.                                          542,146   |
  340.                                                    |
  341. _____________________________________________      |
  342.  Block of bytes pointed to by ptrToPixImage. \_____|
  343.  In the case of the screen, this is $E12000. /
  344. ____________________________________________/
  345.  
  346.            Figure 5-Sample LocInfo and portRect, Both Offset
  347.  
  348. Now if a user moves a mouse to the upper-left corner of the screen, a call to 
  349. GetMouse returns a value of -98,-54, as expected, and if a user moves the 
  350. mouse to the upper-left corner of the portRect, a call to GetMouse returns 
  351. 0,0, again as expected.  This is how origins work and how the conceptual 
  352. drawing space relates to the grafPort.  The boundsRect of the grafPort (in the 
  353. LocInfo record of the grafPort) and the portRect of the grafPort are offset 
  354. when one calls SetOrigin.  It is that simple.
  355.  
  356. Now that it is simple, time to complicate matters with one more player in the 
  357. QuickDraw II clipping world:  the visRgn.
  358.  
  359. The visRgn exists for one purpose:  to cause more clipping.  It never causes 
  360. anything to be clipped less than the portRect does, and in the case of a top 
  361. window that is completely visible, the visRgn and the portRect are exactly the 
  362. same size.  Even more than that, the enclosing rectangle for the visRgn (every 
  363. region has an enclosing rectangle) is this case would be exactly the same as 
  364. that of the portRect.  This all makes sense when one looks at the purpose of a 
  365. visRgn.  Again, the visRgn can only cause more clipping.  If the entire window 
  366. is visible, one does not want more clipping, so a visRgn the same size as the 
  367. portRect guarantees that it does not clip any more than the portRect, as it 
  368. must clip the same amount.
  369.  
  370. The visRgn is a different size than the portRect when the window is not the 
  371. top window and part of it is overlapped (or if part of the window is off the 
  372. screen).  The part that is overlapped is excluded from the visRgn, and this 
  373. excluded part is clipped to protect the window above from being drawn upon.  
  374. This is how window clipping works.  This is all there is to it.
  375.  
  376. Figure 6 enhances Figure 5 by adding an overlapping window to demonstrate the 
  377. visRgn.
  378.  
  379.  __________________ rowBytes _______________
  380. |                                           |
  381. |      boundsRect of current grafPort       |
  382.  ___________________________________________ 
  383. |-98,-54....................................|
  384. |.............intersection rectangle........| portRect of current grafPort
  385. |.......____________________________________|_____________________________
  386. |......|0,0 / / / / / / / / / / / / / / / / |                             |
  387. |......| / / / / / / / / / / / / / / / / / /|                             |
  388. |......|/ / / / / / / / / / / ______________|___________________          |
  389. |......| / / / / / / / / / / |              |                   |         |
  390. |......|/ / / / / / / / / / /|              |                   |         |
  391. |......| /  ^  / / / / / / / |        542,89|                   |         |
  392. |......|____|________________|______________|___________________|_________|
  393. |...........|................|              |                   |      819,89
  394. |..^........|................|              |                   |
  395. |__|________|________________|______________|                   |
  396.    |        |                |           542,146                |
  397.    |        |                |__________________________________|
  398.    |        |                 portRect of some overlapping window
  399.    |        |    ____________________________
  400.    |        |___/ visRgn of current grafPort
  401.    |            \____________________________
  402.    |             _____________________________________________
  403.    |____________/ Block of bytes pointed to by ptrToPixImage.
  404.                 \ In the case of the screen, this is $E12000.
  405.                  \____________________________________________
  406.  
  407.          Figure 6-Sample LocInfo and portRect With Overlapping Window
  408.  
  409. What happens to the visRgn during a SetOrigin?  Remember that the boundsRect 
  410. and portRect get offset.  The visRgn does too.  Again, if all of these 
  411. elements are offset together, then the relationship between them remains the 
  412. same; they stay the same, relative to one another.  (For more information, see 
  413. Einstein's theory of general relativity.)
  414.  
  415. The final component for clipping is the clipRgn, which is the application's 
  416. property and, therefore, the application's responsibility.  The system sets 
  417. the clipRgn about as big as it can get to start (much bigger than the 
  418. portRect); this is often referred to as arbitrarily large, even though it 
  419. isn't so arbitrary.  The system creates all grafPort structures with a large 
  420. clipRgn, and this can be a problem for certain types of QuickDraw II 
  421. operations.  Since the clipRgn already reaches to the borders of the 
  422. conceptual drawing space, it cannot be offset; it is effectively stuck, due to 
  423. its size.  It is a good practice to make the clipRgn smaller than the system 
  424. default.
  425.  
  426. SetOrigin does not offset the clipRgn.  (This is why the size problem with a 
  427. big clipRgn is not so apparent.)  The clipRgn is the only clipping component 
  428. that is not offset by SetOrigin, and one should consider this when using 
  429. clipRgn for clipping effects, since an application must remember to offset it 
  430. if it needs to be offset.
  431.  
  432. Now with all of the fundamentals out of the way, it is time to play some 
  433. grafPort clipping games.  As a refresher, there are four clipping components 
  434. in a grafPort:  the boundsRect, the portRect, the visRgn, and the clipRgn.
  435.  
  436. If an application creates its own off-screen grafPort structures, then it can 
  437. do as it wishes with all four clipping components.  After all, if it has the 
  438. responsibility to set them up in the first place, it should have the right to 
  439. change them.  If, however, the Window Manager creates the grafPort structures, 
  440. then an application should keeps its figurative hands off certain clipping 
  441. components, namely the boundsRect and the visRgn.  The clipRgn, by definition, 
  442. is the application's to do with as it sees fit, and if careful, an application 
  443. can also change the portRect.  Changing the portRect can be very useful, but 
  444. one needs to be careful and fully understand all of the ramifications.
  445.  
  446. So, why would one change the portRect, and how would one do it?
  447.  
  448. Another figure is in order.
  449.  
  450.  __________________ rowBytes _______________
  451. |                                           |
  452. |      boundsRect                           |
  453.  ___________________________________________ 
  454. |-98,-54....................................|
  455. |.............intersection rectangle........|         portRect
  456. |.......____________________________________|_____________________________
  457. |......|0,0 / /|100,0 / / / / / / / / / / / |                             |
  458. |......| / / / | / / / / / / / / / / / / / /|                             |
  459. |......|/ / / /|/ / / / / / / / / / / / / / |                             |
  460. |......| / / / | / / / / / / / / / / / / / /|                             |
  461. |......|/ / / /|/ / / / / / / / / / / / / / |                             |
  462. |......| / / / | / / / / / / / / / /  542,89|                             |
  463. |......|_______|____________________________|_____________________________|
  464. |...........................................|                          819,89
  465. |........................................<__|______
  466. |___________________________________________|      |
  467.                                          542,146   |
  468.                                                    |
  469. _____________________________________________      |
  470.  Block of bytes pointed to by ptrToPixImage. \_____|
  471.  In the case of the screen, this is $E12000. /
  472. ____________________________________________/
  473.  
  474.                 Figure 7-Sample LocInfo and Modified portRect
  475.  
  476. One can use the GetPortRect call to get the portRect for the current grafPort.  
  477. One can then modify it, and then use the SetPortRect call to inform the 
  478. grafPort about the change.  Why do this?  In Figure 7, the dotted line 
  479. represents the new left edge of the portRect after the modification (a simple 
  480. modification of adding 100 to the old value of zero).
  481.  
  482. Note that changing the portRect in this way changes the relationship between 
  483. the portRect and the boundsRect.  Anything drawn from 0 to 99 (x coordinate) 
  484. is clipped, since it is outside the new (modified) portRect.  Before the 
  485. modification, anything drawn from 0 to 99 would have affected the screen.
  486.  
  487. This modification may cause the portRect to be smaller than the visRgn.  This 
  488. is okay, since the visRgn can only cause more clipping, not less.  So, all of 
  489. this works just fine.  Note that the origin changed when the left edge of the 
  490. portRect changed.  The upper-left corner of the portRect is always the origin, 
  491. and an application changed it.  The origin changed without a SetOrigin call.  
  492. (Scary, huh?)
  493.  
  494. One could have done exactly the same thing by making a clipRgn to exclude the 
  495. x coordinates from 0 to 99.  However, here is something cool.  After the 
  496. modification, do a SetOrigin(0,0), which sets the upper-left corner of the 
  497. shrunk portRect to 0,0.  One cannot accomplish this sort of thing as simply by 
  498. making a clipRgn.  One can effectively move where an origin of 0,0 is the 
  499. screen, and just building a clipRgn to exclude some part of the screen does 
  500. not accomplish this.
  501.  
  502. Why would one want to change where 0,0 is on the screen?  This sort of trick 
  503. is very useful for adding rulers to a document window, for example.  One of 
  504. the problems with rulers is that they should not scroll with the rest of a 
  505. document.  Unfortunately, TaskMaster, if allowed to handle scrolling, doesn't 
  506. know about a ruler at the top of a window and scrolls it with the rest of the 
  507. window's content area.  By changing the portRect so that the ruler is not 
  508. inside of it, one can keep TaskMaster from scrolling it.  In a draw procedure, 
  509. when it is necessary to draw the ruler, grow the portRect, set the origin to 
  510. 0,0, and then draw the ruler.  Once it is drawn, set the portRect back to the 
  511. smaller size to protect the ruler again.
  512.  
  513. Another reason one might want to do this is if an application uses a split 
  514. window (where the top of the window may show a different part of the document 
  515. than the bottom).  Changing the portRect has the advantage that the upper-left 
  516. corner of the portRect is always the origin, so it makes mapping document 
  517. coordinates easier.
  518.  
  519. Another advantage to using the portRect in this way is that it keeps the 
  520. clipRgn free for other purposes.  Being able to separate types of clipping to 
  521. either the portRect or the clipRgn keeps the clipRgn from being overused.
  522.  
  523. As a final note, it should be observed that the only clipping that is done is 
  524. on a destination pixelmap.  There is no clipping on a source pixelmap.  There 
  525. is no need.  All the clipping needed is done at the destination end, so it 
  526. would be wasteful to clip twice.
  527.  
  528. This finishes the discussion about QuickDraw II and how the boundsRect, 
  529. portRect, visRgn, and clipRgn work together to accomplish clipping.  Hopefully 
  530. this Note answers more questions than it creates.
  531.  
  532.  
  533. Further Reference
  534. _____________________________________________________________________________
  535.   o  Apple IIGS Toolbox Reference, Volume 2
  536.   o  Relativity the Special and General Theory (1920)
  537.  
  538.